﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HotelBookingSystem
{
    public class HotelManager : Manager, IHotelInfo, IHotelBooking, IHotelAdmin
    {
        private const int MaxDay = 366;
        private const int MaxUnit = 200;
        //private ArrayList cities;
        private ListWithChangedEvent cities = new ListWithChangedEvent();
        public int NumberCities
        {
            get { return cities.Count; }
        }
        public HotelManager()
            : base(MaxDay, MaxUnit)
        {
          cities = new ListWithChangedEvent();
            AddHotel("Sofia", "Sheraton", 250, 135M);
        }

        public string AddHotel(string city, string hotelName, int number, decimal cost)
        {
            if (FindId(city, hotelName) != -1)//add exception
                {
                 return "Hotel is already listed.";
                }
            Hotel hotel = new Hotel(city, hotelName, number, cost);
            AddUnit(hotel);
            EventListener listener = new EventListener(cities);
            AddCity(city);
            listener.Detach();
            return "OK";
        }

        public string DeleteHotel(string city, string name)
        {
            Hotel hotel = new Hotel(city, name, 0, 0M);
            if (units.Contains(hotel))
            {
                units.Remove(hotel);
                DeleteCity(city);
                return "OK";
            }
            return "Room not found"; 
        }

        public string ChangeRooms(string city, string name, int numberRooms, decimal rate)
        {
            foreach (Bookable unit in units)
            {
                Hotel hotel = (Hotel)unit;
                if ((hotel.City == city) && (hotel.HotelName == name))
                {
                    hotel.NumberRooms = numberRooms;
                    hotel.Rate = rate;
                    return "OK";
                }
            }
            return "Room not found"; 
        }

        private void AddCity(string city)
        {
            // check if city already on list, add if not
            if (!cities.Contains(city))
                cities.Add(city);
        }

        private void DeleteCity(string city)
        {
            // If no more hotels in city, delete the city
            // from the cities list
            bool found = false;
            foreach (Bookable unit in units)
            {
                Hotel hotel = (Hotel)unit;
                if (city == hotel.City)
                {
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                try
                {
                    if (cities.Contains(city))
                        cities.Remove(city);
                    else
                        throw new NotFoundException();
                }
                catch (NotFoundException)
                {
                    Console.WriteLine("City not found!");
                }
               
            }
        }

        public int FindId(string city, string name)
        {
            for (int i = 0; i < NumberUnits; i++)
            {
                Hotel hotel = (Hotel)units[i];
                if ((hotel.City == city)
                    && (hotel.HotelName == name))
                    return hotel.HotelId;
            }
            return -1;
        }
        public ArrayList GetHotels()
        {
            ArrayList list = new ArrayList();
            for (int i = 0; i < NumberUnits; i++)
            {
                Hotel hotel = (Hotel)units[i];
                HotelListItem item;
                item.City = hotel.City;
                item.HotelName = hotel.HotelName;
                item.NumberRooms = hotel.NumberRooms;
                item.Rate = hotel.Rate;
                list.Add(item);
            }
            return list;
        }

        public ArrayList GetHotels(string city)
        {
            ArrayList list = new ArrayList();
            for (int i = 0; i < NumberUnits; i++)
            {
                Hotel hotel = (Hotel)units[i];
                HotelListItem item;
                if (city == hotel.City)
                {
                    item.City = hotel.City;
                    item.HotelName = hotel.HotelName;
                    item.NumberRooms = hotel.NumberRooms;
                    item.Rate = hotel.Rate;
                    list.Add(item);
                }
            }
            return list;
        }
        public ArrayList GetCities()
        {
            return cities;
        }

        public ArrayList FindBookingsForClient(int clientId)
        {
            ArrayList list = new ArrayList();
            for (int i = 0; i < NumberReservations; i++)
            {
                HotelBooking res = (HotelBooking)bookings[i];
                BookingListItem item;
                if (clientId == -1 || clientId == res.ClientId)
                {
                    item.ClientId = res.ClientId;
                    item.BookingId = res.BookingId;
                    item.HotelName = res.HotelName;
                    item.City = res.City;
                    item.ArrivalDate = res.ArrivalDate;
                    item.DepartureDate = res.DepartureDate;
                    item.NumberDays = res.NumberDays;
                    list.Add(item);
                }
            }
            return list;
        }

        public void ShowHotels()
        {
            for (int i = 0; i < NumberUnits; i++)
            {
                Hotel hotel = (Hotel)units[i];
                string city = hotel.City.PadRight(12);
                string name = hotel.HotelName.PadRight(12);
                string rooms = hotel.NumberRooms.ToString().PadLeft(4);
                string rate = string.Format("{0, 10:C}", hotel.Rate);
                string str = city + "   " + name + "   " + rooms + "   " + rate;
                Console.WriteLine(str);
            }
        }

        public void ShowHotels(string city)
        {
            for (int i = 0; i < NumberUnits; i++)
            {
                Hotel hotel = (Hotel)units[i];
                if (city == hotel.City)
                {
                    string scity = hotel.City.PadRight(12);
                    string name = hotel.HotelName.PadRight(12);
                    string rooms = hotel.NumberRooms.ToString().PadLeft(4);
                    string rate = string.Format("{0, 10:C}", hotel.Rate);
                    string str = scity + "   " + name + "   " + rooms + "   " + rate;
                    Console.WriteLine(str);
                }
            }
        }
        public void ShowCities()
        {
            for (int i = 0; i < NumberCities; i++)
                Console.WriteLine(cities[i]);
        }

        public BookingResult Book(int customerId, string city, string name,
            DateTime dt, int numDays, TypeBookable type)
        {
            int id = FindId(city, name);
            //if (id == -1)
            //{
            //    ReservationResult result = new ReservationResult();
            //    result.ReservationId = -1;
            //    result.Comment = "Hotel not found";
            //    return result;
            //}held by HotelIdException
            HotelBooking res = new HotelBooking();
            res.UnitId = id;
            res.ClientId = customerId;
            res.HotelName = name;
            res.City = city;
            res.ArrivalDate = dt;
            res.DepartureDate = dt + new TimeSpan(numDays, 0, 0, 0);
            res.NumberDays = numDays;
            res.bookableType = type;
            return Book(res);
        }
        public void ShowBookings(int clientId)
        {
            for (int i = 0; i < NumberReservations; i++)
            {
                HotelBooking res = (HotelBooking)bookings[i];
                if (clientId == -1 || clientId == res.ClientId)
                {
                    string id = res.ClientId.ToString().PadRight(4);
                    string rid = res.BookingId.ToString().PadRight(4);
                    string hotel = res.HotelName.PadRight(12);
                    string city = res.City.PadRight(12);
                    string arrive = res.ArrivalDate.ToString("d").PadRight(10);
                    string depart = res.DepartureDate.ToString("d").PadRight(10);
                    string number = res.NumberDays.ToString();
                    string str = id + "  " + rid + "  " + hotel + "  " + city +
                        "  " + arrive + "  " + depart + "  " + number;
                    Console.WriteLine(str);
                }
            }
        }
    }
}